package com.syh.niceweibo.common;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Environment;
import android.util.Log;

/**
 * 
 * @author SYH ahong2011@Gmail.com 2012-7-11
 * 
 */
public class LogUtils {
    /**
     * if need to Forbid log,change DEBUG to false
     */
    public final static boolean DEBUG = true;

    private final static int LogInfo = 3;
    private final static int LogDebug = 2;
    private final static int LogError = 1;

    private final static long MAX_FILE_SIZE = 2 * 1024 * 1024;
    private final static String LOG_FILE = "/"+Constants.APP_DIR+"/log/";
    private static SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
    private static SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public final static boolean switchWriteFile = true;
    private final static int logLevel = LogInfo;

    public static void i(String TAG, String msg) {
        if (logLevel >= LogInfo) {
            msg = getStackTraceMessage(TAG, msg);
            Log.i(TAG, msg);
            if (switchWriteFile) {
                try {
                    write(LogInfo, msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void d(String TAG, String msg) {
        if (logLevel >= LogDebug) {
            msg = getStackTraceMessage(TAG, msg);
            Log.d(TAG, msg);
            if (switchWriteFile) {
                try {
                    write(LogDebug, msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void e(String TAG, String msg) {
        if (logLevel >= LogError) {
            msg = getStackTraceMessage(TAG, msg);
            Log.e(TAG, msg);
            if (switchWriteFile) {
                try {
                    write(LogError, msg);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void e(String TAG, String msg, Throwable tr) {
        e(TAG, msg + " e:" + getThrowableMessage(tr));
    }

    private static void write(int logLevel, String msg) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            long time = System.currentTimeMillis();
            File logFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                    + LOG_FILE + format1.format(new Date(time)) + ".txt");
            if (!logFile.getParentFile().exists()) {
                logFile.getParentFile().mkdirs();
            }

            int i = 1;
            while (logFile.exists() && logFile.length() > MAX_FILE_SIZE) {
                logFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                        + LOG_FILE + format1.format(new Date(time)) + i + ".txt");
                i++;
            }

            StringBuffer sbf = new StringBuffer();

            sbf.append("\r\n");
            sbf.append(format2.format(new Date(time)));
            if (logLevel == LogInfo) {
                sbf.append(" info ");
            } else if (logLevel == LogDebug) {
                sbf.append(" debug ");
            } else if (logLevel == LogError) {
                sbf.append(" error ");
            }

            sbf.append(msg);

            OutputStream out = null;
            try {
                out = new BufferedOutputStream(new FileOutputStream(logFile, true));
                out.write(sbf.toString().getBytes());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private static String getStackTraceMessage(String TAG, String msg) {
        try {
            StackTraceElement caller = new Throwable().fillInStackTrace().getStackTrace()[2];
            return new StringBuilder().append(TAG.toLowerCase()).append(":").append(msg)
                    .append(" :").append(caller.getClassName()).append(".")
                    .append(caller.getMethodName()).append("() ").toString();
        } catch (Exception e) {
            e.printStackTrace();
            return msg;
        }
    }

    public static String getThrowableMessage(Throwable tr) {
        if (tr != null) {
            try {
                StringBuffer logBuffer = new StringBuffer();
                logBuffer.append(tr.getClass());
                logBuffer.append(":");
                logBuffer.append(tr.getMessage());
                logBuffer.append("\r\n");

                StackTraceElement[] messages = tr.getStackTrace();
                for (StackTraceElement element : messages) {
                    logBuffer.append(element);
                    logBuffer.append("\r\n");
                }
                return logBuffer.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

}
